import { AxiosInstance } from 'axios'
import { sleep } from '../../Utils'

import { createRequest, wrapperSend } from './request'
import { FailResponse, Response } from './responses'

export type CallBack = () => void
export type ErrorHandle = (status: number) => void

export class ApiBaseOptions {
  token?: string
  userID?: number
  avatarurl?:string

  onError?: ErrorHandle
  beforeSend?: CallBack
  afterSend?: CallBack

  setCredentials(token?: string, userID?: number,avatarurl?:string) {
    this.token = token
    this.userID = userID
    this.avatarurl = avatarurl
  }

  removeCredentials() {
    this.token = undefined
    this.userID = undefined
    this.avatarurl = undefined
  }

  setOnError(onError: ErrorHandle) {
    this.onError = onError
  }

  setBeforeSend(beforeSend: CallBack) {
    this.beforeSend = beforeSend
  }

  setAfterSend(afterSend: CallBack) {
    this.afterSend = afterSend
  }
}

type RequestOption = {
  back: boolean
  encrypt: boolean
}

const defaultOption: RequestOption = {
  back: false,
  encrypt: true,
}

export class ApiBase {
  request: AxiosInstance
  apiOption?: ApiBaseOptions

  constructor(apiOption: ApiBaseOptions) {
    this.request = createRequest()
    this.apiOption = apiOption
  }

  protected post = async <T = any>(
    url = '',
    body: any = {},
    requestOption?: RequestOption
  ) => {
    requestOption = {
      ...defaultOption,
      ...(requestOption || {}),
    }

    if (requestOption.back && this.apiOption?.beforeSend) {
      this.apiOption.beforeSend()
    }
    let encrypt = body
    // 加密暂时省略

    const [res] = await Promise.all<Response<any> | FailResponse, unknown>([
      wrapperSend(
        () =>
          this.request.post(url, encrypt, {
            headers: {
              token: this.apiOption?.token,
              user_id: this.apiOption?.userID,
            },
          }),
        this.apiOption?.onError
      ),
      sleep(500),
    ])

    if (requestOption.back && this.apiOption?.afterSend) {
      this.apiOption.afterSend()
    }

    if (res.success) {
      return res as Response<T>
    } else {
      return res as FailResponse
    }
  }

  protected delete = async (
    url = '',
    requestOption?: RequestOption
  ) => {
    requestOption = {
      ...defaultOption,
      ...(requestOption || {}),
    }

    if (requestOption.back && this.apiOption?.beforeSend) {
      this.apiOption.beforeSend()
    }
    // 加密暂时省略

    const [res] = await Promise.all<Response<any> | FailResponse, unknown>([
      wrapperSend(
        () =>
          this.request.delete(url, {
            headers: {
              token: this.apiOption?.token,
              user_id: this.apiOption?.userID,
            },
          }),
        this.apiOption?.onError
      ),
      sleep(500),
    ])

    if (requestOption.back && this.apiOption?.afterSend) {
      this.apiOption.afterSend()
    }

    if (res.success) {
      return res 
    } else {
      return res as FailResponse
    }
  }
}
